"""
IP管理服务
提供IP地址的CRUD操作和业务逻辑
"""

import logging
import ipaddress
from typing import List, Optional, Dict, Any
from sqlalchemy.orm import Session
from sqlalchemy import and_, or_, func

from src.app.database.models import IpManagement, Asset, OperatingSystem, BusinessSystem, Middleware, OobManagement
from src.app.database.database import get_database_manager
from src.app.modules.ip.cache import IpCache
from src.app.modules.ip.utils import IpUtils

logger = logging.getLogger(__name__)

class IpService:
    """IP管理服务类"""
    
    def __init__(self):
        self.db_manager = get_database_manager()
        self.cache = IpCache()
        self.utils = IpUtils()
    
    def create_ip(self, ip_data: Dict[str, Any]) -> Dict[str, Any]:
        """
        创建IP地址
        
        Args:
            ip_data: IP地址数据
            
        Returns:
            创建结果
        """
        # 验证数据
        is_valid, error_msg = self.utils.validate_ip_data(ip_data)
        if not is_valid:
            return {'success': False, 'message': error_msg}
        
        # 检查IP是否重复
        with self.db_manager.get_session() as session:
            existing_ip = session.query(IpManagement).filter(
                IpManagement.ip == ip_data['ip']
            ).first()
            
            if existing_ip:
                return {'success': False, 'message': f"IP地址 {ip_data['ip']} 已存在"}
        
        try:
            # 创建IP对象
            ip = IpManagement(
                ip=ip_data['ip'],
                subnet_mask=ip_data['subnet_mask'],
                vlan=ip_data['vlan'],
                purpose=ip_data['purpose'],
                status=ip_data['status'],
                allocation_duration=ip_data['allocation_duration'],
                asset_id=ip_data.get('asset_id'),
                os_id=ip_data.get('os_id'),
                system_id=ip_data.get('system_id'),
                mw_id=ip_data.get('mw_id'),
                oob_id=ip_data.get('oob_id'),
                os_name=ip_data.get('os_name'),
                hostname=ip_data.get('hostname'),
                description=ip_data.get('description')
            )
            
            # 保存到数据库
            with self.db_manager.get_session() as session:
                session.add(ip)
                session.commit()
                session.refresh(ip)
            
            # 清除缓存
            self.cache.clear_cache()
            
            logger.info(f"创建IP地址成功: {ip.ip}")
            return {'success': True, 'data': self.utils.ip_to_dict(ip)}
            
        except Exception as e:
            logger.error(f"创建IP地址失败: {str(e)}")
            return {'success': False, 'message': f"创建失败: {str(e)}"}
    
    def update_ip(self, ip: str, ip_data: Dict[str, Any]) -> Dict[str, Any]:
        """
        更新IP地址
        
        Args:
            ip: IP地址
            ip_data: 更新数据
            
        Returns:
            更新结果
        """
        # 验证数据
        is_valid, error_msg = self.utils.validate_ip_data(ip_data, is_update=True)
        if not is_valid:
            return {'success': False, 'message': error_msg}
        
        try:
            with self.db_manager.get_session() as session:
                # 查找IP记录
                ip_record = session.query(IpManagement).filter(
                    IpManagement.ip == ip
                ).first()
                
                if not ip_record:
                    return {'success': False, 'message': f"IP地址 {ip} 不存在"}
                
                # 更新字段
                for field, value in ip_data.items():
                    if hasattr(ip_record, field) and value is not None:
                        setattr(ip_record, field, value)
                
                session.commit()
                session.refresh(ip_record)
            
            # 清除缓存
            self.cache.clear_cache()
            
            logger.info(f"更新IP地址成功: {ip}")
            return {'success': True, 'data': self.utils.ip_to_dict(ip_record)}
            
        except Exception as e:
            logger.error(f"更新IP地址失败: {str(e)}")
            return {'success': False, 'message': f"更新失败: {str(e)}"}
    
    def delete_ip(self, ip: str) -> Dict[str, Any]:
        """
        删除IP地址
        
        Args:
            ip: IP地址
            
        Returns:
            删除结果
        """
        try:
            with self.db_manager.get_session() as session:
                # 查找IP记录
                ip_record = session.query(IpManagement).filter(
                    IpManagement.ip == ip
                ).first()
                
                if not ip_record:
                    return {'success': False, 'message': f"IP地址 {ip} 不存在"}
                
                # 删除记录
                session.delete(ip_record)
                session.commit()
            
            # 清除缓存
            self.cache.clear_cache()
            
            logger.info(f"删除IP地址成功: {ip}")
            return {'success': True, 'message': '删除成功'}
            
        except Exception as e:
            logger.error(f"删除IP地址失败: {str(e)}")
            return {'success': False, 'message': f"删除失败: {str(e)}"}
    
    def get_ip_by_ip(self, ip: str) -> Dict[str, Any]:
        """
        根据IP地址获取IP信息
        
        Args:
            ip: IP地址
            
        Returns:
            IP信息
        """
        # 先从缓存获取
        cached_data = self.cache.get_ip(ip)
        if cached_data:
            return cached_data
        
        try:
            with self.db_manager.get_session() as session:
                ip_record = session.query(IpManagement).filter(
                    IpManagement.ip == ip
                ).first()
                
                if ip_record:
                    data = self.utils.ip_to_dict(ip_record)
                    # 缓存数据
                    self.cache.set_ip(ip, data)
                    return data
                else:
                    return None
                    
        except Exception as e:
            logger.error(f"获取IP信息失败: {str(e)}")
            return None
    
    def get_all_ips(self, filters: Optional[Dict[str, Any]] = None) -> List[Dict[str, Any]]:
        """
        获取所有IP地址
        
        Args:
            filters: 筛选条件
            
        Returns:
            IP地址列表
        """
        try:
            with self.db_manager.get_session() as session:
                query = session.query(IpManagement)
                
                # 应用筛选条件
                if filters:
                    if 'vlan' in filters and filters['vlan']:
                        query = query.filter(IpManagement.vlan == filters['vlan'])
                    if 'status' in filters and filters['status']:
                        query = query.filter(IpManagement.status == filters['status'])
                    if 'purpose' in filters and filters['purpose']:
                        query = query.filter(IpManagement.purpose.like(f"%{filters['purpose']}%"))
                    if 'hostname' in filters and filters['hostname']:
                        query = query.filter(IpManagement.hostname.like(f"%{filters['hostname']}%"))
                    if 'ip' in filters and filters['ip']:
                        query = query.filter(IpManagement.ip.like(f"%{filters['ip']}%"))
                
                # 按IP地址排序
                query = query.order_by(IpManagement.ip)
                
                ip_records = query.all()
                return [self.utils.ip_to_dict(ip) for ip in ip_records]
                
        except Exception as e:
            logger.error(f"获取IP地址列表失败: {str(e)}")
            return []
    
    def get_ip_statistics(self) -> Dict[str, Any]:
        """
        获取IP地址统计信息
        
        Returns:
            统计信息
        """
        try:
            with self.db_manager.get_session() as session:
                # 总数统计
                total_count = session.query(func.count(IpManagement.ip)).scalar()
                
                # 按状态统计
                status_stats = session.query(
                    IpManagement.status,
                    func.count(IpManagement.ip).label('count')
                ).group_by(IpManagement.status).all()
                
                # 按VLAN统计
                vlan_stats = session.query(
                    IpManagement.vlan,
                    func.count(IpManagement.ip).label('count')
                ).group_by(IpManagement.vlan).all()
                
                # 按用途统计
                purpose_stats = session.query(
                    IpManagement.purpose,
                    func.count(IpManagement.ip).label('count')
                ).group_by(IpManagement.purpose).all()
                
                return {
                    'total_count': total_count,
                    'status_distribution': {stat.status: stat.count for stat in status_stats},
                    'vlan_distribution': {stat.vlan: stat.count for stat in vlan_stats},
                    'purpose_distribution': {stat.purpose: stat.count for stat in purpose_stats}
                }
                
        except Exception as e:
            logger.error(f"获取IP统计信息失败: {str(e)}")
            return {
                'total_count': 0,
                'status_distribution': {},
                'vlan_distribution': {},
                'purpose_distribution': {}
            }
    
    def get_available_ips(self, subnet: str, count: int = 10) -> List[str]:
        """
        获取可用的IP地址
        
        Args:
            subnet: 子网（如192.168.1.0/24）
            count: 返回数量
            
        Returns:
            可用IP地址列表
        """
        try:
            # 解析子网
            network = ipaddress.ip_network(subnet, strict=False)
            available_ips = []
            
            # 获取已使用的IP
            with self.db_manager.get_session() as session:
                used_ips = set()
                used_ip_records = session.query(IpManagement.ip).all()
                for record in used_ip_records:
                    used_ips.add(record.ip)
            
            # 查找可用IP
            for ip in network.hosts():
                if str(ip) not in used_ips:
                    available_ips.append(str(ip))
                    if len(available_ips) >= count:
                        break
            
            return available_ips
            
        except Exception as e:
            logger.error(f"获取可用IP地址失败: {str(e)}")
            return []
    
    def check_ip_conflict(self, ip: str, exclude_ip: Optional[str] = None) -> bool:
        """
        检查IP地址冲突
        
        Args:
            ip: IP地址
            exclude_ip: 排除的IP地址（用于更新时检查）
            
        Returns:
            是否冲突
        """
        try:
            with self.db_manager.get_session() as session:
                query = session.query(IpManagement).filter(IpManagement.ip == ip)
                if exclude_ip:
                    query = query.filter(IpManagement.ip != exclude_ip)
                
                existing_ip = query.first()
                return existing_ip is not None
                
        except Exception as e:
            logger.error(f"检查IP冲突失败: {str(e)}")
            return False
    
    def get_binding_entities(self, ip: str) -> Dict[str, Any]:
        """
        获取IP绑定的实体信息
        
        Args:
            ip: IP地址
            
        Returns:
            绑定的实体信息
        """
        try:
            with self.db_manager.get_session() as session:
                ip_record = session.query(IpManagement).filter(
                    IpManagement.ip == ip
                ).first()
                
                if not ip_record:
                    return None
                
                entity_info = {}
                
                # 获取绑定的实体信息
                if ip_record.asset_id:
                    asset = session.query(Asset).filter(
                        Asset.asset_id == ip_record.asset_id
                    ).first()
                    if asset:
                        entity_info['asset'] = {
                            'type': '设备资产',
                            'name': asset.asset_name,
                            'code': asset.asset_code,
                            'asset_type': asset.asset_type
                        }
                
                if ip_record.os_id:
                    os = session.query(OperatingSystem).filter(
                        OperatingSystem.os_id == ip_record.os_id
                    ).first()
                    if os:
                        entity_info['os'] = {
                            'type': '操作系统',
                            'name': os.os_name,
                            'version': os.version
                        }
                
                if ip_record.system_id:
                    system = session.query(BusinessSystem).filter(
                        BusinessSystem.system_id == ip_record.system_id
                    ).first()
                    if system:
                        entity_info['system'] = {
                            'type': '业务系统',
                            'name': system.system_name,
                            'system_type': system.system_type
                        }
                
                if ip_record.mw_id:
                    middleware = session.query(Middleware).filter(
                        Middleware.mw_id == ip_record.mw_id
                    ).first()
                    if middleware:
                        entity_info['middleware'] = {
                            'type': '中间件',
                            'name': middleware.name,
                            'mw_type': middleware.mw_type
                        }
                
                if ip_record.oob_id:
                    oob = session.query(OobManagement).filter(
                        OobManagement.oob_id == ip_record.oob_id
                    ).first()
                    if oob:
                        entity_info['oob'] = {
                            'type': '带外管理',
                            'name': oob.login_url
                        }
                
                return entity_info
                
        except Exception as e:
            logger.error(f"获取IP绑定实体信息失败: {str(e)}")
            return None
    
    def batch_update_status(self, ips: List[str], status: str) -> Dict[str, Any]:
        """
        批量更新IP状态
        
        Args:
            ips: IP地址列表
            status: 新状态
            
        Returns:
            更新结果
        """
        try:
            with self.db_manager.get_session() as session:
                updated_count = session.query(IpManagement).filter(
                    IpManagement.ip.in_(ips)
                ).update({'status': status}, synchronize_session=False)
                
                session.commit()
            
            # 清除缓存
            self.cache.clear_cache()
            
            logger.info(f"批量更新IP状态成功: {updated_count}条记录")
            return {
                'success': True, 
                'message': f"成功更新{updated_count}条记录",
                'updated_count': updated_count
            }
            
        except Exception as e:
            logger.error(f"批量更新IP状态失败: {str(e)}")
            return {'success': False, 'message': f"批量更新失败: {str(e)}"}
    
    def import_ips(self, ip_data_list: List[Dict[str, Any]]) -> Dict[str, Any]:
        """
        批量导入IP地址
        
        Args:
            ip_data_list: IP数据列表
            
        Returns:
            导入结果
        """
        success_count = 0
        error_count = 0
        errors = []
        
        for ip_data in ip_data_list:
            result = self.create_ip(ip_data)
            if result['success']:
                success_count += 1
            else:
                error_count += 1
                errors.append(f"IP {ip_data.get('ip', 'unknown')}: {result['message']}")
        
        return {
            'success': error_count == 0,
            'success_count': success_count,
            'error_count': error_count,
            'errors': errors
        }